package cn.wokoba.service.activity.service.quota;


import cn.wokoba.service.activity.model.*;
import cn.wokoba.service.activity.repository.ActivityRepository;
import cn.wokoba.service.activity.service.quota.policy.ITradePolicy;
import cn.wokoba.service.activity.service.quota.rule.IActionChain;
import cn.wokoba.service.activity.service.quota.rule.factory.DefaultActivityChainFactory;
import cn.wokoba.service.credit.repository.CreditRepository;
import cn.wokoba.types.enums.ResponseCode;
import cn.wokoba.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;

//抽奖活动抽象类，定义标准的流程
@Slf4j
public abstract class AbstractRaffleActivityAccountQuota {
    protected ActivityRepository activityRepository;
    protected DefaultActivityChainFactory defaultActivityChainFactory;
    private final Map<String, ITradePolicy> tradePolicyGroup;

    protected final CreditRepository creditRepository;
    public AbstractRaffleActivityAccountQuota(ActivityRepository activityRepository, DefaultActivityChainFactory defaultActivityChainFactory, Map<String, ITradePolicy> tradePolicyGroup, CreditRepository creditRepository) {
        this.activityRepository = activityRepository;
        this.defaultActivityChainFactory = defaultActivityChainFactory;
        this.tradePolicyGroup = tradePolicyGroup;
        this.creditRepository = creditRepository;
    }


    public UnpaidActivityOrderEntity createOrder(SkuRechargeEntity skuRechargeEntity) {
        // 1.1 参数校验
        String userId = skuRechargeEntity.getUserId();
        Long sku = skuRechargeEntity.getSku();
        String outBusinessNo = skuRechargeEntity.getOutBusinessNo();
        if (null == sku || StringUtils.isBlank(userId) || StringUtils.isBlank(outBusinessNo)) {
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }

        //1.2 检查用户积分是否足够
        if(!checkUserCredit(userId, sku)){
            throw new AppException(ResponseCode.ACTIVITY_USER_CREDIT_ERROR.getCode(), ResponseCode.ACTIVITY_USER_CREDIT_ERROR.getInfo());
        }

        // 2. 查询未支付订单「一个月以内的未支付订单」
        UnpaidActivityOrderEntity unpaidCreditOrder =  activityRepository.queryUnpaidActivityOrder(skuRechargeEntity);
        if (null != unpaidCreditOrder) return unpaidCreditOrder;

        // 3. 查询基础信息「sku、活动、次数」
        ActivitySkuEntity activitySkuEntity = activityRepository.queryActivitySku(sku);
        ActivityEntity activityEntity = activityRepository.queryRaffleActivityByActivityId(activitySkuEntity.getActivityId());
        ActivityCountEntity activityCountEntity = activityRepository.queryRaffleActivityCountByActivityCountId(activitySkuEntity.getActivityCountId());

        // 4. 活动动作规则校验 「过滤失败则直接抛异常」- 责任链扣减sku库存
        IActionChain actionChain = defaultActivityChainFactory.openActionChain();
        actionChain.action(activitySkuEntity, activityEntity, activityCountEntity);

        // 5. 构建订单聚合对象
        CreateQuotaOrderAggregate createOrderAggregate = buildOrderAggregate(skuRechargeEntity, activitySkuEntity, activityEntity, activityCountEntity);

        // 6. 交易策略 - 【积分兑换，支付类订单】【返利无支付交易订单，直接充值到账】【订单状态变更交易类型策略】
        ITradePolicy tradePolicy = tradePolicyGroup.get(skuRechargeEntity.getOrderTradeType().getCode());
        tradePolicy.trade(createOrderAggregate);

        // 7. 返回订单信息
        ActivityOrderEntity activityOrderEntity = createOrderAggregate.getActivityOrderEntity();
        return UnpaidActivityOrderEntity.builder()
                .userId(userId)
                .orderId(activityOrderEntity.getOrderId())
                .outBusinessNo(activityOrderEntity.getOutBusinessNo())
                .payAmount(activityOrderEntity.getPayAmount())
                .build();
    }

    protected abstract CreateQuotaOrderAggregate buildOrderAggregate(SkuRechargeEntity skuRechargeEntity, ActivitySkuEntity activitySkuEntity, ActivityEntity activityEntity, ActivityCountEntity activityCountEntity);

    protected abstract boolean checkUserCredit(String userId, Long sku);

}
